/*===============================================================
 *   Copyright (C) 2017 All rights reserved.
 *   
 *   文件名称：lib.c
 *   创 建 者：陈迪林
 *   创建日期：2017年08月02日
 *   描    述：
 *
 *   更新日志：
 *
 ================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <dirent.h>
#include <time.h>
#include "lib.h"

#include <sqlite3.h>

void fill_args(char *p[],  char *buf)
{
    while(*buf)
    {
        if(*buf!=' ' && *(buf-1)==' ')
        {
            *p++ = buf;
            *(buf-1) = 0;
        }

        buf++;
    }
}

int callback(void *para, int f_num, char **f_value, char **f_name)
{
    int i;

    char *pPara = (char *)para;

    if(0 == strncmp(f_value[0],pPara,20) && 0 == strncmp(f_value[1], pPara+20,20))
    {
        pPara[40] = 1;
    }

    return 0;
}


int yanzhen_sqlite(const char *name, const char *passwd)
{
    sqlite3 *db;
    
    if(sqlite3_open("sql_data.db",&db) != SQLITE_OK)
    {
        printf("error: %s\n",sqlite3_errmsg(db));
        return -1;
    }
    
    char *errmsg;

    char para[41];
    bzero(para,41);

    memcpy(para, name, 20);
    memcpy(para+20, passwd, 20);
    
    if(SQLITE_OK != sqlite3_exec(db,"select * from user_info", callback, para, &errmsg))
    {
        printf("error: %s\n",errmsg);
        return -1;
    }

    sqlite3_close(db);

    if(para[40] == 1)return 0;
    else return -1;

}

int insert_sqlite(const char *name, const char *pawssd)
{
    sqlite3 *db;
    
    if(sqlite3_open("sql_data.db",&db) != SQLITE_OK)
    {
        printf("error: %s\n",sqlite3_errmsg(db));
        return -1;
    }
    
    char *errmsg;

    char buff[100];
    sprintf(buff,"insert into user_info values(\"%s\",\"%s\")", name,pawssd);

    if(SQLITE_OK != sqlite3_exec(db, buff, callback, NULL, &errmsg))
    {
        printf("error: %s\n",errmsg);
        return -1;
    }

    sqlite3_close(db);
    return 0;
}

int datayan(int sockfd, char *cur_usrname)
{
    int lag = 0; //验证用户
    do
    {
        char name[20]={0}, passwd[20]={0},*args[10],buff[100]={0},nbuff[100]={0};
        int n;
yanzhen:

        n = read(sockfd, buff, 100);

//        printf("%s\n",buff);
        nbuff[0] = ' ';
        
        memcpy(nbuff+1, buff, 99);

        fill_args(args, nbuff);
        
        if(0 == strncmp(args[0], "quit", 4))
        {
            close(sockfd);
  //          printf("close\n");
            return -1;
        }

        read(sockfd, name, 20);
        
//        printf("nameover\n");
        read(sockfd, passwd, 20);

//        printf("passwd over\n");
        memcpy(cur_usrname, name, 20);
        

        if(0 == strncmp(args[0], "Login",5))
        {
//            printf("name=%s passwd=%s\n",name, passwd);

            if(0 ==  yanzhen_sqlite(name, passwd))//r返回0说明用户名密码正确
            {
                char flag = 1;
                write(sockfd, &flag, 1);
                lag = 1;
            }
            else 
            {
                char flag = 0;
                write(sockfd, &flag, 1); 
                lag = 0;
            }
        }
        else if(0 == strncmp(args[0], "Register",8))
        { 
  //          printf("name=%s passwd=%s\n",name, passwd);
            if(0 ==  insert_sqlite(name, passwd))
            {
                char flag = '1';
                lag = 1;
                sprintf(buff, "./userdir/%s_dir", name);
                if(0 != mkdir(buff, 0666))
                {
                    if(errno == EEXIST)
                    {
                        flag = '2';
                        write(sockfd, &flag, 1);
                    }
                    else
                    {
                        flag = '3';
                        write(sockfd, &flag, 1);        
                    }
                    goto yanzhen;
                }
                else
                {   
                    flag = '1';
                    write(sockfd, &flag, 1);
                }
            }
            else 
            {
                char flag = '0';
                write(sockfd, &flag, 1);
                lag = 0;
            }
        }
    }while(lag == 0);

    return 0;
}

void *thread_func(void *sock)
{
    int cliensock = *((int *)sock);
    char buff[1500] = {0};
    char nbuff[100] = {0};
    char cur_usrname[20];

    if(-1 == datayan(cliensock, cur_usrname))
    {

 //       printf("exit()\n");
        return NULL;
    }

//    printf("cur_usrname: %s\n",cur_usrname);

    while(1)
    {
        int n = read(cliensock, buff, 100);
        
        char *args[10];
        nbuff[0] = ' ';
        memcpy(nbuff+1, buff, 99);

        fill_args(args, nbuff);

       // printf("cur_usrname: %s\n",cur_usrname);
        if(0 == strcmp(args[0], "get"))
        {
            char bf[100];
            sprintf(bf, "./userdir/%s_dir/%s", cur_usrname, args[1]);
      //      printf("cur_usrname: %s\n",cur_usrname);
            int fd = open(bf, O_RDONLY); //打开文件出错,返回错误消息
            if(-1 == fd)
            {
                sprintf(buff, "get error: %s", strerror(errno));
                write(cliensock, buff, 100);
            }
            else
            {
                struct stat file_info;
                int file_size; 
                if(-1 == stat(bf,&file_info))
                {
                    perror("file stat");
                }
                file_size = file_info.st_size;

                write(cliensock, &file_size, 100); //先发送文件大小

                while(n = read(fd, buff, 1500)) //循环发送文件,直到发完
                {
                    write(cliensock, buff, n);
                }
            }
        }
        else if(0 == strcmp(args[0], "put"))
        {
            char bf[100];
            sprintf(bf, "./userdir/%s_dir/%s", cur_usrname, args[1]);
            int n = read(cliensock, buff, 100);
            int filesize = *((int *)buff);
            int size = 0;
            int fd = open(bf, O_CREAT | O_WRONLY | O_TRUNC, 0666);
            while(n = read(cliensock, buff, 500))
            { 
                size+=n;
                write(fd, buff, n);
                if(size == filesize) //若接收完毕，则跳出循环，如果不这样判断，在没有受到数据时，read不会返回
                    break;
            }
        }
        else if(0 == strncmp(args[0], "ls",2))
        {
            char bf[500];
            char *pbf = bf;
       //     printf("cur_usrname: %s\n",cur_usrname);
            sprintf(bf, "./userdir/%s_dir", cur_usrname);
            DIR *dir = opendir(bf);
            struct dirent *file;
            while((file = readdir(dir)) != NULL)
            {
                if((0 != strcmp(".",file->d_name)) && (0 != strcmp("..",file->d_name)))
                {
                    char s[100]={0};
                    sprintf(pbf,"%s  ",file->d_name);
                    sprintf(s,"%s  ",file->d_name);
                    pbf += strlen(s);
                }
            }
            write(cliensock, bf, 500);
        }
        else if(0 == strcmp(args[0], "q"))
        {
            close(cliensock);
            break;
        }
        else
        {
            continue;            
        }

    }
}
